package org.aeon.message;

import lombok.Data;
import org.aeon.message.request.*;
import org.aeon.message.response.*;

import java.io.Serial;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;

/**
 * @author: MissingAeon
 * @date: 2024/1/25 11:24
 * @description:
 */
@Data
public abstract class Message implements Serializable {

    public static final int UserInfoRequestMessage = 10;                        // 用户信息请求消息
    public static final int UserInfoResponseMessage = 11;                       // 用户信息响
    public static final int GroupInfoRequestMessage = 20;                       // 群聊信息请求消息
    public static final int GroupInfoResponseMessage = 21;                      // 群聊信息响
    public static final int LoginRequestMessage = 101;                          // 登录请求消息
    public static final int LoginResponseMessage = 102;                         // 登录响应消息
    public static final int RegisterRequestMessage = 111;                       // 注册请求消息
    public static final int RegisterResponseMessage = 112;                      // 注册响应消息
    public static final int ChatRequestMessage = 201;                           // 聊天请求消息
    public static final int ChatResponseMessage = 202;                          // 聊天响应消息

    public static final int GroupCreateRequestMessage = 301;                    // 组创建请求消息
    public static final int GroupCreateResponseMessage = 302;                   // 组创建响应消息
    public static final int GroupJoinRequestMessage = 303;                      // 群组加入请求消息
    public static final int GroupJoinResponseMessage = 304;                     // 组加入响应消息
    public static final int GroupQuitRequestMessage = 305;                      // 组退出请求消息
    public static final int GroupQuitResponseMessage = 306;                     // 组退出响应消息
    public static final int GroupChatRequestMessage = 307;                      // 群聊请求消息
    public static final int GroupChatResponseMessage = 308;                     // 群聊响应消息
    public static final int GroupMembersRequestMessage = 309;                   // 组成员请求消息
    public static final int GroupMembersResponseMessage = 310;                  // 组成员响应消息

    public static final int GroupsListRequestMessage = 320;                     // 组列表请求消息
    public static final int GroupsListResponseMessage = 321;                    // 组列表响应消息

    public static final int ListQueryRequestMessage = 401;                      // 关系列表请求消息
    public static final int ListQueryResponseMessage = 402;                     // 关系列表请求消息

    public static final int FriendAddRequestMessage = 403;                      // 好友添加请求消息
    public static final int FriendAddResponseMessage = 404;                     // 好友添加响应消息
    public static final int FriendDeleteRequestMessage = 405;                   // 好友删除请求消息
    public static final int FriendDeleteResponseMessage = 406;                  // 好友删除响应消息

    public static final int FriendApplyListRequestMessage = 407;                // 好友申请列表请求消息
    public static final int FriendApplyListResponseMessage = 408;               // 好友申请列表响应消息

    public static final int BlacklistModifyRequestMessage = 413;                // 黑名单修改请求消息
    public static final int BlacklistModifyResponseMessage = 414;               // 黑名单修改响应消息

    public static final int FriendApplyRequestMessage = 417;                    // 好友申请请求消息
    public static final int FriendApplyResponseMessage = 418;                   // 好友申请响应消息

    public static final int SearchRequestMessage = 800;                         // 搜索请求消息
    public static final int SearchResponseMessage = 801;                        // 搜索响应消息

    public static final int PingMessage = 1000;
    public static final int PongMessage = 1001;

    public static final int CancelLoginRequestMessage = 9970;
    public static final int RequestLoginResponseMessage = 9980;
    public static final int IllegalRequestResponseMessage = 9999;
    private static final Map<Integer, Class<? extends Message>> messageClasses = new HashMap<>();   // 消息类型查询集合
    @Serial
    private static final long serialVersionUID = -8456727256549632892L;

    static {
        messageClasses.put(UserInfoRequestMessage, UserInfoRequestMessage.class);
        messageClasses.put(UserInfoResponseMessage, UserInfoResponseMessage.class);
        messageClasses.put(GroupInfoRequestMessage, GroupInfoRequestMessage.class);
        messageClasses.put(GroupInfoResponseMessage, GroupInfoResponseMessage.class);

        messageClasses.put(LoginRequestMessage, LoginRequestMessage.class);
        messageClasses.put(LoginResponseMessage, LoginResponseMessage.class);
        messageClasses.put(RegisterRequestMessage, RegisterRequestMessage.class);
        messageClasses.put(RegisterResponseMessage, RegisterResponseMessage.class);

        messageClasses.put(ChatRequestMessage, ChatRequestMessage.class);
        messageClasses.put(ChatResponseMessage, ChatResponseMessage.class);

        messageClasses.put(GroupCreateRequestMessage, GroupCreateRequestMessage.class);
        messageClasses.put(GroupCreateResponseMessage, GroupCreateResponseMessage.class);
        messageClasses.put(GroupJoinRequestMessage, GroupJoinRequestMessage.class);
        messageClasses.put(GroupJoinResponseMessage, GroupJoinResponseMessage.class);
        messageClasses.put(GroupQuitRequestMessage, GroupQuitRequestMessage.class);
        messageClasses.put(GroupQuitResponseMessage, GroupQuitResponseMessage.class);
        messageClasses.put(GroupChatRequestMessage, GroupChatRequestMessage.class);
        messageClasses.put(GroupChatResponseMessage, GroupChatResponseMessage.class);
        messageClasses.put(GroupMembersRequestMessage, GroupMembersRequestMessage.class);
        messageClasses.put(GroupMembersResponseMessage, GroupMembersResponseMessage.class);

        messageClasses.put(GroupsListRequestMessage, GroupsListRequestMessage.class);
        messageClasses.put(GroupsListResponseMessage, GroupsListResponseMessage.class);

        messageClasses.put(FriendApplyRequestMessage, FriendApplyRequestMessage.class);
        messageClasses.put(FriendApplyResponseMessage, FriendApplyResponseMessage.class);

        messageClasses.put(ListQueryRequestMessage, ListQueryRequestMessage.class);
        messageClasses.put(ListQueryResponseMessage, ListQueryResponseMessage.class);
        messageClasses.put(FriendAddRequestMessage, FriendAddRequestMessage.class);
        messageClasses.put(FriendAddResponseMessage, FriendAddResponseMessage.class);
        messageClasses.put(FriendDeleteRequestMessage, FriendDeleteRequestMessage.class);
        messageClasses.put(FriendDeleteResponseMessage, FriendDeleteResponseMessage.class);

        messageClasses.put(BlacklistModifyRequestMessage, BlacklistModifyRequestMessage.class);
        messageClasses.put(BlacklistModifyResponseMessage, BlacklistModifyResponseMessage.class);

        messageClasses.put(SearchRequestMessage, SearchRequestMessage.class);
        messageClasses.put(SearchResponseMessage, SearchResponseMessage.class);

        messageClasses.put(PingMessage, PingMessage.class);
        messageClasses.put(PongMessage, PongMessage.class);

        messageClasses.put(CancelLoginRequestMessage, CancelLoginRequestMessage.class);
        messageClasses.put(RequestLoginResponseMessage, RequestLoginResponseMessage.class);
        messageClasses.put(IllegalRequestResponseMessage, IllegalRequestResponseMessage.class);
    }

    private final String uid;
    private final int messageType;
    private int sequenceId;

    public Message() {
        uid = UUID.randomUUID().toString();
        messageType = getMessageType();
    }

    public static Class<?> getMessageClass(int messageType) {
        return messageClasses.get(messageType);
    }

    public abstract int getMessageType();

    @Override
    public final boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Message message = (Message) o;
        return uid.equals(message.uid);
    }

    @Override
    public final int hashCode() {
        return Objects.hash(uid);
    }
}
